#include "MainWindow.h"
namespace LightChart
{
MainWindow::MainWindow(QWidget* parent) : QMainWindow(parent), gco(this), pw(this), ct(this)
    {
	Ui_MainWindow::setupUi(this);
	setupConnections();
    }
    void MainWindow::setupConnections()
    {
	connect(chartsList, SIGNAL(itemClicked(QListWidgetItem*)),this, SLOT(onChartsItemActivated(QListWidgetItem *)));
	connect(axesList, SIGNAL(itemClicked(QListWidgetItem*)),this, SLOT(onAxesItemActivated(QListWidgetItem *)));
	connect(availableSeries, SIGNAL(itemDoubleClicked(QListWidgetItem*)), this, SLOT(onPreviewClicked(QListWidgetItem*)));
	connect(chosenSeries, SIGNAL(itemDoubleClicked(QListWidgetItem*)), this, SLOT(onPreviewClicked(QListWidgetItem*)));
	connect(seriesAddButton, SIGNAL(clicked()),this, SLOT(onAddSeriesClicked()));
	connect(seriesRemoveButton, SIGNAL(clicked()),this, SLOT(onRemoveSeriesClicked()));
	connect(axesOptionsButton, SIGNAL(clicked()),this, SLOT(onAxesOptionsClicked()));
	connect(chartOptionsButton, SIGNAL(clicked()),this, SLOT(onChartOptionsClicked()));
	connect(newChartButton, SIGNAL(clicked()),this, SLOT(onNewChartClicked()));
	connect(deleteChartButton, SIGNAL(clicked()),this, SLOT(onDeleteChartClicked()));
	connect(plotButton, SIGNAL(clicked()), this, SLOT(onPlotButtonClicked()));
	connect(actionOpen, SIGNAL(triggered()), this, SLOT(onActionOpen()));
	connect(actionSave, SIGNAL(triggered()), this, SLOT(onActionSave()));
	connect(actionExit, SIGNAL(triggered()), this, SLOT(onActionExit()));
	connect(actionParseFile, SIGNAL(triggered()), this, SLOT(onActionParseFile()));
	connect(actionNewChart, SIGNAL(triggered()), this, SLOT(onActionNewChart()));
	connect(actionGlobalOptions, SIGNAL(triggered()), this, SLOT(onActionGlobalOptions()));
	connect(actionPlotAll, SIGNAL(triggered()), this, SLOT(onActionPlotAll()));
	connect(actionAbout, SIGNAL(triggered()), this, SLOT(onActionAbout()));
	connect(actionAboutQt,SIGNAL(triggered()),qApp,SLOT(aboutQt()));
	connect(actionAuthors, SIGNAL(triggered()), this, SLOT(onActionAuthors()));
	connect(&pw, SIGNAL(onFinishClicked()), this, SLOT(onRefreshAvalibleSeries()));
	connect(&ct, SIGNAL(onFinishClicked()), this, SLOT(onRefreshCharts()));
    }
    void MainWindow::onChartsItemActivated(QListWidgetItem * item)
    {
        axesList->clear();
        Chart * chart = static_cast<QListWidgetEnhancedItem<Chart *> *>(item)->get_value();
        std::map<Axis *, std::vector<Series *> > & map = Storage::get_instance().charts[chart];
        for(auto it = map.begin(); it != map.end(); ++it) {
            QString label ((*it).first->get_label().c_str());
            QListWidgetEnhancedItem<Axis *> * axis_item = new QListWidgetEnhancedItem<Axis *>(label, axesList);
            axis_item->set_value((*it).first);
        }
    }
    void MainWindow::onAxesItemActivated(QListWidgetItem * item)
    {
        chosenSeries->clear();
        Axis * axis = static_cast<QListWidgetEnhancedItem<Axis *> *>(item)->get_value();
        std::vector<Series*> & series = Storage::get_instance().charts[axis->get_owner()][axis];
        for(auto it = series.begin(); it != series.end(); ++it) {
            QIcon icon;
            switch((*it)->get_type()) {
            case INTEGER:
                icon.addFile(":/graphics/DataTypes/series_int.png");
                break;
            case DOUBLE_PRECISION:
                icon.addFile(":/graphics/DataTypes/series_double.png");
                break;
            case S_TEXT:
                icon.addFile(":/graphics/DataTypes/series_string.png");
                break;
            case UNKNOWN:
                break;
            }
            QString label ((*it)->get_name().c_str());
            QListWidgetEnhancedItem<Series *> * series_item = new QListWidgetEnhancedItem<Series *>(icon, label, chosenSeries);
            series_item->set_value(*it);
        }
    }
    void MainWindow::onPreviewClicked(QListWidgetItem * item)
    {
        SeriesPreview& preview = SeriesPreview::get_instance(this);
        preview.show();
        QListWidgetEnhancedItem<Series*> * series_item = static_cast<QListWidgetEnhancedItem<Series*> *>(item);
        preview.displaySeries(series_item->get_value());
    }
    void MainWindow::onAddSeriesClicked()
    {
	if (axesList->currentItem()) {
            if (availableSeries->currentItem()) {
                Axis * axis = static_cast<QListWidgetEnhancedItem<Axis *> *>(axesList->currentItem())->get_value();
                Series * series = static_cast<QListWidgetEnhancedItem<Series *> *>(availableSeries->currentItem())->get_value();
                Storage::get_instance().charts[axis->get_owner()][axis].push_back(series);
                onAxesItemActivated(axesList->currentItem());
            } else {
                QMessageBox::information(this, "Information", "To add series, select it and proper Axis.");
            }
        } else {
            QMessageBox::information(this, "Information", "To add series, select it and proper Axis.");
        }
    }
    void MainWindow::onRemoveSeriesClicked()
    {
        if (axesList->currentItem()) {
                if (chosenSeries->currentItem()) {
                    Axis * axis = static_cast<QListWidgetEnhancedItem<Axis *> *>(axesList->currentItem())->get_value();
                    Series * series = static_cast<QListWidgetEnhancedItem<Series *> *>(chosenSeries->currentItem())->get_value();
                    std::vector<Series *> & series_vector  = Storage::get_instance().charts[axis->get_owner()][axis];
                    series_vector.erase(std::find(series_vector.begin(), series_vector.end(), series));
                    onAxesItemActivated(axesList->currentItem());
                } else {
                    QMessageBox::information(this, "Information", "To remove series, select it and proper Axis.");
                }
            } else {
                QMessageBox::information(this, "Information", "To remove series, select it and proper Axis.");
            }
    }
    void MainWindow::onAxesOptionsClicked()
    {
	QListWidgetItem* current = 0;
	if((current = axesList->currentItem()))
	{
	    Axis* axis = static_cast<QListWidgetEnhancedItem<Axis*> *>(axesList->currentItem())->get_value();
	    AxisSettings* settings = new AxisSettings(this,axis); //leave MainWindow as a parent, because it is used in AxisSettins
	    settings->show();
	}
    }
    void MainWindow::onChartOptionsClicked()
    {
	if(chartsList->currentItem())
	{
	    Chart* chart = static_cast<QListWidgetEnhancedItem<Chart*> *>(chartsList->currentItem())->get_value();
	    chart->showOptions();
	}
    }
    void MainWindow::onNewChartClicked()
    {
	onActionNewChart();
    }
    void MainWindow::onDeleteChartClicked()
    {
        if (chartsList->currentItem()) {
            Storage::get_instance().charts.remove(static_cast<QListWidgetEnhancedItem<Chart*>*>(chartsList->currentItem())->get_value());
            //chartsList->removeItemWidget(chartsList->currentItem()); // WTF? Doesnt work
            axesList->clear();
            chosenSeries->clear();
            onRefreshCharts();
        }
    }
    void MainWindow::onPlotButtonClicked()
    {
	if(chartsList->currentItem())
	{
	    Chart* chart = static_cast<QListWidgetEnhancedItem<Chart*> *>(chartsList->currentItem())->get_value();
	    chart->draw();
	}
    }

    void MainWindow::onActionOpen()
    {
        QString file = "";
        file = QFileDialog::getOpenFileName(this,tr("Open file"),QString("."), tr("LightChart Settings (*.lcs)"));
        if(!file.isEmpty())
        {
            try {
                std::ifstream ifs(file.toStdString());
                boost::archive::text_iarchive archive (ifs);
                archive >> Storage::get_instance();
                RefreshAll();
            }
            catch (boost::archive::archive_exception & e) {
                QMessageBox::critical(this, "Error in serialization.", e.what());
            }
        }
    }
    void MainWindow::onActionSave()
    {
        QString fileName = QFileDialog::getSaveFileName(0,tr("Save as dialog"),QString("."),tr("LightChart Settings (*.lcs)"));
        if(!fileName.isEmpty())
        {
            if(fileName.indexOf(".lcs") == -1)
            {
                fileName += ".lcs";
            }
            try {
                std::ofstream ofs(fileName.toStdString());
                boost::archive::text_oarchive archive (ofs);
                archive << Storage::get_instance();
            }
            catch (boost::archive::archive_exception & e) {
                QMessageBox::critical(this, "Error in serialization.", e.what());
            }
        }
    }
    void MainWindow::onActionExit()
    {
        QCoreApplication::exit(0);
    }
    void MainWindow::onActionParseFile()
    {
        pw.show();
    }
    void MainWindow::onActionNewChart()
    {
        ct.show();
    }
    void MainWindow::onActionGlobalOptions()
    {
        gco.show();
    }
    void MainWindow::onActionPlotAll()
    {
	ChartsStorage& charts = Storage::get_instance().charts;
	ChartsStorage::const_iterator it;
	for(it = charts.begin(); it != charts.end(); ++it)
	    (*it).first->draw();
    }
    void MainWindow::onRefreshAvalibleSeries() {
        SeriesStorage & ss = Storage::get_instance().series;
        availableSeries->clear();
        QIcon icon;
        for (auto it = ss.begin(); it != ss.end(); ++it) {
            QString label ((*it).get_name().c_str());
            switch((*it).get_type()) {
            case INTEGER:
                icon.addFile(":/graphics/DataTypes/series_int.png");
                break;
            case DOUBLE_PRECISION:
                icon.addFile(":/graphics/DataTypes/series_double.png");
                break;
            case S_TEXT:
                icon.addFile(":/graphics/DataTypes/series_string.png");
                break;
            case UNKNOWN:
                break;
            }
            QListWidgetEnhancedItem<Series *> * item  = new QListWidgetEnhancedItem<Series *>(icon, label, availableSeries);
            item->set_value(&*it);
        }
    }
    void MainWindow::onRefreshCharts() {
        chartsList->clear();
        ChartsStorage & cs = Storage::get_instance().charts;
        for (auto it = cs.begin(); it != cs.end(); ++it) {
            Chart * chart = (*it).first;
            QString title (chart->get_title().c_str());
            QListWidgetEnhancedItem<Chart *> * item = new QListWidgetEnhancedItem<Chart *>(title, chartsList);
            item->set_value(chart);
        }
    }
    void MainWindow::RefreshAll() {
        onRefreshCharts();
        axesList->clear();
        chosenSeries->clear();
        onRefreshAvalibleSeries();
    }
    void MainWindow::onActionAbout()
    {
	QMessageBox::about(this,tr("About LightChart"),tr("<h2>LightChart v.0.9a</h2>"
							  "<p>LightChart allows you to customize and plot a few basic chart types.</p>"));
    }
    void MainWindow::onActionAuthors()
    {
	QMessageBox::about(this,tr("About authors"),tr("<h2>Authors</h2>"
        "<p>Przemyslaw Plutecki, Maciej Siczek.</p>"));
    }
}
